package com.feilong.modules.service.home.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.feilong.modules.client.auth.AuthClient;
import com.feilong.modules.common.constant.UploadConstant;
import com.feilong.modules.common.exception.APIException;
import com.feilong.modules.common.request.WxOperateDbRequest;
import com.feilong.modules.common.utils.ImageUtils;
import com.feilong.modules.model.goods.request.GetUploadRequest;
import com.feilong.modules.model.home.enums.UploadTypeEnum;
import com.feilong.modules.model.home.request.UpdateSwiperRequest;
import com.feilong.modules.model.home.vo.SwiperInfoVO;
import com.feilong.modules.service.home.HomeInfoService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;

@Slf4j
@Service
public class HomeInfoServiceImpl implements HomeInfoService {

    @Value("${feilongshop.config.appid}")
    private String APPID;

    @Value("${feilongshop.config.app-secret}")
    private String APPSECRET;

    @Value("${feilongshop.config.env}")
    private String ENV;

    @Value("${feilongshop.config.file-prefix}")
    private String FILE_PREFIX;

    @Value("${feilongshop.wx-cloud.swiper-image-path-prefix}")
    private String SWIPER_PATH_PREFIX;

    @Value("${feilongshop.wx-cloud.floor-image-path-prefix}")
    private String FLOOR_PATH_PREFIX;

    @Resource
    private AuthClient authClient;

    /**
     * 从云开发数据库获取首页轮播图信息
     * @return
     */
    @Override
    public List<SwiperInfoVO> getSwiperList() {
        // 获取AccessToken
        String token = getAccessToken();
        WxOperateDbRequest request = new WxOperateDbRequest();
        request.setEnv(ENV);
        // 根据swiper_id升序获取
        request.setQuery("db.collection(\"swiper\").orderBy('swiper_id','asc').get()");
        String result = authClient.queryCloudDbInfo(request, token);
        // 获取轮播图信息
        return getSwiperData(result);
    }

    /**
     * 上传图片到微信云开发服务器
     * @param file
     * @param type
     * @param fileName
     * @return
     */
    @Override
    public String uploadImage(MultipartFile file, Integer type, String fileName) {
        // 校验图片格式，只能上传jpg、jpeg、png、gif
        if (!ImageUtils.verifyImageSuffix(file)) {
            throw new APIException(UploadConstant.IMAGE_FORMAT_ERROR);
        }
        LocalDateTime now = LocalDateTime.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String time = now.format(formatter);
        // 获取文件后缀名
        String ext = StringUtils.substringAfterLast(file.getOriginalFilename(),".");
        // 根据fileName和后缀名拼接图片上传至微信云开服服务器的path
        // 拼上时间，防止重复上传回显读上一张图片的问题
        // 判断上传类型
        String path;
        if (type.equals(UploadTypeEnum.SWIPER.getCode())) {
            path = SWIPER_PATH_PREFIX + fileName + " " + time + "." + ext;
        } else {
            path = FLOOR_PATH_PREFIX + fileName + " " + time + "." + ext;
        }
        // 获取AccessToken
        String token = getAccessToken();
        GetUploadRequest getUploadRequest = new GetUploadRequest();
        getUploadRequest.setEnv(ENV);
        getUploadRequest.setPath(path);
        // 获取上传链接
        String result = authClient.getUploadUrl(getUploadRequest,token);
        JSONObject data = JSONObject.parseObject(result);
        // 上传图片
        return upload(file, data, path);
    }

    /**
     * 根据轮播图id更新云开发数据库信息
     * @param request
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateSwiper(UpdateSwiperRequest request) {
        // 获取AccessToken
        String token = getAccessToken();
        WxOperateDbRequest updateRequest = new WxOperateDbRequest();
        updateRequest.setEnv(ENV);
        updateRequest.setQuery("db.collection(\"swiper\").where({swiper_id:" + request.getSwiperId() + "}).update({" +
                "data: {" +
                "image_src:\"" + request.getImageSrc() + "\"," +
                "is_show:" + request.getIsShow() + "," +
                "navigate_url:\"" + request.getNavigateUrl() + "\"," +
                "open_type:\"" + request.getOpenType() + "\"}})"
        );
        String result = authClient.updateCloudDbInfo(updateRequest, token);
        log.info("更新云开发数据库轮播图信息，更新结果： {}", result);
    }

    /**
     * 获取轮播图列表
     * @param result
     * @return
     */
    private List<SwiperInfoVO> getSwiperData(String result) {
        List<SwiperInfoVO> list = new ArrayList<>();
        JSONObject resultObject = JSON.parseObject(result);
        // 先取出data
        JSONArray data = resultObject.getJSONArray("data");
        if (data.size() != 0) {
            // 转换为list
            data.forEach(item ->{
                JSONObject jsonObject = JSONObject.parseObject(item.toString());
                SwiperInfoVO swiperInfo = jsonObject.toJavaObject(SwiperInfoVO.class);
                list.add(swiperInfo);
            });
        }
        return list;
    }

    /**
     * RestTemplate方式发送Post请求上传图片
     * @param file
     * @param data
     * @param path
     */
    public String upload(MultipartFile file, JSONObject data, String path){
        try{
            // 处理上传url，原本返回的url中文名称会进行编码，需要替换编码为中文名称
            String fileName = StringUtils.substringAfterLast(path,"/");
            String url = StringUtils.substringBeforeLast(data.getString("url"),"/") + "/" + fileName;
            RestTemplate restTemplate = new RestTemplate();
            HttpHeaders headers = new HttpHeaders();
            MultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
            map.add("key",path);
            map.add("Signature",data.getString("authorization"));
            map.add("x-cos-security-token",data.getString("token"));
            map.add("x-cos-meta-fileid",data.getString("cos_file_id"));
            map.add("file",file.getBytes());
            headers.setContentType(MediaType.MULTIPART_FORM_DATA);
            HttpEntity<MultiValueMap<String, Object>> param = new HttpEntity<>(map, headers);
            //发起请求，服务地址，请求参数，返回消息体的数据类型
            ResponseEntity<String> response = restTemplate.postForEntity(url, param, String.class);
            //body
            String body = response.getBody();
            log.info(url + " 请求返回值： " + body);
        } catch (Exception e) {
            log.error("上传图片失败，失败原因： " + e);
            throw new APIException(UploadConstant.IMAGE_UPLOAD_FAIL);
        }
        return FILE_PREFIX + path;
    }

    /**
     * 获取小程序AccessToken
     * @return
     */
    public String getAccessToken(){
        String result = authClient.getAccessToken(APPID,APPSECRET);
        JSONObject data = JSONObject.parseObject(result);
        String token = data.getString("access_token");
        log.info("获取到的微信云开发AccessToken为 -> {}", token);
        return token;
    }
}
